fix(hackathons): route draft deletion to org-scoped endpoint#433
Conversation
|
@ryzen-xp is attempting to deploy a commit to the Threadflow Team on Vercel. A member of the Team first needs to authorize it. |
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughAdded type-aware deletion for hackathons: the UI, deletion hook, and API now distinguish between 'draft' and 'hackathon' and route deletes to the correct endpoint accordingly. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Page as Page Component
participant Hook as useDeleteHackathon Hook
participant API as API Layer
participant Backend as Backend
User->>Page: Click delete (draft or published)
Page->>Page: handleDeleteClick(id, type) — store `hackathonToDelete` with `type`
Page->>User: Show Delete confirmation
User->>Page: Confirm deletion
Page->>Hook: call delete with (id, type, orgId)
alt type == 'draft'
Hook->>API: deleteDraft(draftId, organizationId)
API->>Backend: DELETE /organizations/{orgId}/hackathons/draft/{draftId}
else type == 'hackathon'
Hook->>API: deleteHackathon(hackathonId)
API->>Backend: DELETE /api/hackathons/{id}
end
Backend-->>API: 204 / response
API-->>Hook: success/error
Hook-->>Page: onSuccess/onError
Page->>User: show toast using captured title
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hello @0xdevcollins , Can you help me why this return 404 |
Okay... I will fix it now |
|
@ryzen-xp it has been fixed |
|
Hello @0xdevcollins , Please Review !! |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
hooks/hackathon/use-delete-hackathon.ts (1)
19-25: Useconstarrow style for this hook export to match TS conventions in this repo.The hook is currently a function declaration; convert it to a
constarrow with an explicit return type for consistency.As per coding guidelines
**/*.{ts,tsx}: “Prefer const arrow functions with explicit type annotations over function declarations”.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@hooks/hackathon/use-delete-hackathon.ts` around lines 19 - 25, Convert the function declaration export function useDeleteHackathon({...}: UseDeleteHackathonOptions) to a const arrow export: declare const useDeleteHackathon: (opts: UseDeleteHackathonOptions) => ReturnType and assign an arrow function to it, keeping the same parameter destructuring and body; ensure you add an explicit return type (the hook’s return type used elsewhere in the codebase) and keep the existing export behavior so references to useDeleteHackathon continue to work.lib/api/hackathons/draft.ts (1)
41-45: Avoid duplicatingDeleteHackathonResponseacross API modules.This interface is already defined in
lib/api/hackathons/core.tsand is structurally identical. Keeping one shared type prevents silent drift.Proposed refactor
import api from '../api'; import { ApiResponse, PaginatedResponse } from '../types'; import type { HackathonDraft, Hackathon } from '@/types/hackathon'; +import type { DeleteHackathonResponse } from './core'; @@ -export interface DeleteHackathonResponse extends ApiResponse<null> { - success: true; - message: string; - data: null; -}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/api/hackathons/draft.ts` around lines 41 - 45, Duplicate interface DeleteHackathonResponse exists in this module; delete the local declaration and instead import and reuse the single exported DeleteHackathonResponse from the core module where it’s defined, or re-export that core type if this module needs to expose it; ensure any references in this file use the imported type and update the module exports accordingly to avoid type duplication and drift.app/(landing)/organizations/[id]/hackathons/page.tsx (1)
167-191: RefactorhandleDeleteClickto use early returns and reduce nesting.The branching works, but flattening this with early returns will make the control flow easier to maintain.
Proposed refactor
const handleDeleteClick = ( hackathonId: string, type: 'draft' | 'hackathon' ) => { - if (type === 'hackathon') { - const published = publishedHackathons.find(h => h.id === hackathonId); - if (published) { - setHackathonToDelete({ - id: hackathonId, - title: published.name || 'Untitled Hackathon', - type: 'hackathon', - }); - setDeleteDialogOpen(true); - } - } else { - const draft = draftHackathons.find(d => d.id === hackathonId); - if (draft) { - setHackathonToDelete({ - id: hackathonId, - title: draft.data.information?.name || 'Untitled Hackathon', - type: 'draft', - }); - setDeleteDialogOpen(true); - } - } + if (type === 'hackathon') { + const published = publishedHackathons.find(h => h.id === hackathonId); + if (!published) return; + setHackathonToDelete({ + id: hackathonId, + title: published.name || 'Untitled Hackathon', + type: 'hackathon', + }); + setDeleteDialogOpen(true); + return; + } + + const draft = draftHackathons.find(d => d.id === hackathonId); + if (!draft) return; + setHackathonToDelete({ + id: hackathonId, + title: draft.data.information?.name || 'Untitled Hackathon', + type: 'draft', + }); + setDeleteDialogOpen(true); };As per coding guidelines
**/*.{js,jsx,ts,tsx}: “Use early returns to improve code clarity”.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(landing)/organizations/[id]/hackathons/page.tsx around lines 167 - 191, Refactor handleDeleteClick to use early returns: first branch on the type (if type === 'hackathon') then find the published item via publishedHackathons.find; if not found return immediately, otherwise call setHackathonToDelete({ id: hackathonId, title: published.name || 'Untitled Hackathon', type: 'hackathon' }) and setDeleteDialogOpen(true) and return; for the 'draft' path find the draft from draftHackathons, return if missing, otherwise call setHackathonToDelete({ id: hackathonId, title: draft.data.information?.name || 'Untitled Hackathon', type: 'draft' }) and setDeleteDialogOpen(true). Ensure no nested if blocks remain and keep existing variable names (handleDeleteClick, publishedHackathons, draftHackathons, setHackathonToDelete, setDeleteDialogOpen).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/`(landing)/organizations/[id]/hackathons/page.tsx:
- Around line 203-205: The page is firing a duplicate success toast: remove the
extra toast.success call in this component (the one that shows `"${title}" has
been permanently deleted.`) because useDeleteHackathon already emits the toast
on success; locate and delete that toast.success invocation in the component (or
alternatively modify the call site to pass a flag into useDeleteHackathon to
disable the hook's toast and keep the page toast), referencing the toast.success
line in this file and the useDeleteHackathon hook to ensure only one success
notification is produced.
---
Nitpick comments:
In `@app/`(landing)/organizations/[id]/hackathons/page.tsx:
- Around line 167-191: Refactor handleDeleteClick to use early returns: first
branch on the type (if type === 'hackathon') then find the published item via
publishedHackathons.find; if not found return immediately, otherwise call
setHackathonToDelete({ id: hackathonId, title: published.name || 'Untitled
Hackathon', type: 'hackathon' }) and setDeleteDialogOpen(true) and return; for
the 'draft' path find the draft from draftHackathons, return if missing,
otherwise call setHackathonToDelete({ id: hackathonId, title:
draft.data.information?.name || 'Untitled Hackathon', type: 'draft' }) and
setDeleteDialogOpen(true). Ensure no nested if blocks remain and keep existing
variable names (handleDeleteClick, publishedHackathons, draftHackathons,
setHackathonToDelete, setDeleteDialogOpen).
In `@hooks/hackathon/use-delete-hackathon.ts`:
- Around line 19-25: Convert the function declaration export function
useDeleteHackathon({...}: UseDeleteHackathonOptions) to a const arrow export:
declare const useDeleteHackathon: (opts: UseDeleteHackathonOptions) =>
ReturnType and assign an arrow function to it, keeping the same parameter
destructuring and body; ensure you add an explicit return type (the hook’s
return type used elsewhere in the codebase) and keep the existing export
behavior so references to useDeleteHackathon continue to work.
In `@lib/api/hackathons/draft.ts`:
- Around line 41-45: Duplicate interface DeleteHackathonResponse exists in this
module; delete the local declaration and instead import and reuse the single
exported DeleteHackathonResponse from the core module where it’s defined, or
re-export that core type if this module needs to expose it; ensure any
references in this file use the imported type and update the module exports
accordingly to avoid type duplication and drift.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
Run ID: d789430e-1491-4f49-bb1e-5eaeb389d45d
📒 Files selected for processing (4)
app/(landing)/organizations/[id]/hackathons/page.tsxhooks/hackathon/use-delete-hackathon.tslib/api/hackathons/draft.tslib/api/hackathons/index.ts
💤 Files with no reviewable changes (1)
- lib/api/hackathons/index.ts
What's completed:
deleteDraft()inlib/api/hackathons/draft.tstargeting the org-scoped routeDELETE /organizations/:orgId/hackathons/draft/:draftIduseDeleteHackathonhook to accept atypeparam ('draft' | 'hackathon') and route to the correct API functionHackathonsPage(page.tsx) to track and forward the resourcetypethrough the full deletion flowProblem:
Both
draftanddrafts(singular and plural) paths return 404 — the backend DELETE endpoint for draft deletion does not exist. All frontend changes are complete and correct; unblocked only by backend implementing the route.Screencast.From.2026-03-04.08-55-44.mp4
Close #416
Summary by CodeRabbit